/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.tools.idea.imports

import com.android.tools.idea.gradle.project.sync.snapshots.PreparedTestProject
import com.android.tools.idea.projectsystem.PROJECT_SYSTEM_SYNC_TOPIC
import com.android.tools.idea.projectsystem.ProjectSystemSyncManager
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.SettableFuture
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.psi.PsiManager
import org.mockito.kotlin.doReturn
import java.nio.charset.StandardCharsets.UTF_8
import java.util.concurrent.TimeUnit
import org.mockito.kotlin.mock

fun PreparedTestProject.Context.performAndWaitForSyncEnd(invoke: () -> Unit) {
  val publishedResult = SettableFuture.create<ProjectSystemSyncManager.SyncResult>()
  project.messageBus
    .connect(project)
    .subscribe(
      PROJECT_SYSTEM_SYNC_TOPIC,
      object : ProjectSystemSyncManager.SyncResultListener {
        override fun syncEnded(result: ProjectSystemSyncManager.SyncResult) {
          publishedResult.set(result)
        }
      },
    )

  invoke()

  val results = publishedResult.get(10, TimeUnit.SECONDS)
  assertThat(results)
    .named("Second sync result")
    .isEqualTo(ProjectSystemSyncManager.SyncResult.SUCCESS)
}

fun checkBuildGradle(project: Project, buildFilePath: String, check: (String) -> Boolean): Boolean {
  val buildGradle = project.guessProjectDir()!!.findFileByRelativePath(buildFilePath)
  val buildGradlePsi = PsiManager.getInstance(project).findFile(buildGradle!!)

  return check(buildGradlePsi!!.text)
}

fun assertBuildGradle(project: Project, buildFilePath: String = "app/build.gradle", check: (String) -> Boolean) {
  assertThat(checkBuildGradle(project, buildFilePath, check)).isEqualTo(true)
}

val fakeMavenClassRegistryManager: MavenClassRegistryManager
  get() {
    val inputStream =
      // language=JSON
      """
      {
        "Index": [
          {
            "groupId": "androidx.palette",
            "artifactId": "palette-ktx",
            "version": "1.0.0",
            "ktxTargets": [
              "androidx.palette:palette"
            ],
            "fqcns": []
          },
          {
            "groupId": "androidx.palette",
            "artifactId": "palette",
            "version": "1.0.0",
            "ktxTargets": [],
            "fqcns": [
              "androidx.palette.graphics.Palette",
              "androidx.palette.graphics.FakeClass"
            ]
          },
          {
            "groupId": "androidx.room",
            "artifactId": "room-runtime",
            "version": "2.2.6",
            "ktxTargets": [],
            "fqcns": [
              "androidx.room.Room",
              "androidx.room.RoomDatabase",
              "androidx.room.FakeClass"
            ]
          },
          {
            "groupId": "androidx.recyclerview",
            "artifactId": "recyclerview",
            "version": "1.1.0",
            "ktxTargets": [],
            "fqcns": [
              "androidx.recyclerview.widget.RecyclerView"
            ]
          },
          {
            "groupId": "com.google.android.gms",
            "artifactId": "play-services-maps",
            "version": "17.0.1",
            "ktxTargets": [],
            "fqcns": [
              "com.google.android.gms.maps.SupportMapFragment"
            ]
          },
          {
            "groupId": "androidx.camera",
            "artifactId": "camera-core",
            "version": "1.1.0-alpha03",
            "ktxTargets": [],
            "fqcns": [
              "androidx.camera.core.ExtendableBuilder",
              "androidx.camera.core.ImageCapture"
            ],
            "ktlfns": [
              {
                "fqn": "androidx.camera.core.FileFacadeKt.cameraCoreTopLevelFunction"
              }
            ]
          },
          {
            "groupId": "androidx.camera",
            "artifactId": "camera-view",
            "version": "1.0.0-alpha22",
            "ktxTargets": [],
            "fqcns": [
              "androidx.camera.view.PreviewView"
            ]
          },
          {
            "groupId": "androidx.compose.ui",
            "artifactId": "ui-tooling-preview",
            "version": "1.0.5",
            "ktxTargets": [],
            "fqcns": [
              "androidx.compose.ui.tooling.preview.Preview"
            ]
          },
          {
            "groupId": "my.madeup.pkg",
            "artifactId": "amazing-pkg",
            "version": "4.2.0",
            "ktxTargets": [],
            "fqcns": [],
            "ktlfns": [
              {
                "xfqn": "my.madeup.pkg.amazing.StringsKt.extensionFunction",
                "rcvr": "kotlin.String"
              }
            ]
          }
        ]
      }
      """
        .trimIndent()
        .byteInputStream(UTF_8)

    val mavenClassRegistry = MavenClassRegistry.createFrom { inputStream }

    return mock<MavenClassRegistryManager> {
      on { tryGetMavenClassRegistry() } doReturn(mavenClassRegistry)
      onBlocking { getMavenClassRegistry() } doReturn (mavenClassRegistry)
    }
  }